package com.hqy.bean.helper;

import com.hqy.bean.annotation.Conditional;
import com.hqy.bean.annotation.Controller;
import com.hqy.bean.annotation.Service;

import com.hqy.bean.annotation.itf.Condition;
import com.hqy.core.helper.ClassHelper;
import com.hqy.tools.utils.ReflectionUtil;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

public final class BeanHelper {

    /**
     * BEAN_MAP相当于一个Spring容器, 拥有应用所有bean的实例
     */
    private static final Map<Class<?>, Object> BEAN_MAP = new HashMap<Class<?>, Object>();

    static {
        //获取应用中的所有bean
        Set<Class<?>> beanClassSet = getBeanClassSet();
        //将bean实例化, 并放入bean容器中
        for (Class<?> beanClass : beanClassSet) {

            boolean flag =true;

            if(beanClass.isAnnotationPresent(Conditional.class)){
                Class<? extends Condition>[] conditions = beanClass.getAnnotation(Conditional.class).value();

                for(Class<? extends Condition> condition:conditions){
                    try {
                        flag=condition.newInstance().matches();
                        if(!flag){
                            break;
                        }

                    } catch (InstantiationException | IllegalAccessException e) {
                        throw new RuntimeException("实例化Condition失败",e);
                    }
                }

            }
            if(flag){
                Object obj = ReflectionUtil.newInstance(beanClass);
                BEAN_MAP.put(beanClass, obj);
            }
        }
    }

    /**
     * 获取 Bean 容器
     */
    public static Map<Class<?>, Object> getBeanMap() {
        return BEAN_MAP;
    }

    /**
     * 获取 Bean 实例
     */
    @SuppressWarnings("unchecked")
    public static <T> T getBean(Class<T> cls) {
        if (!BEAN_MAP.containsKey(cls)) {
            throw new RuntimeException("can not get bean by class: " + cls);
        }
        return (T) BEAN_MAP.get(cls);
    }

    /**
     * 设置 Bean 实例
     */
    public static void setBean(Class<?> cls, Object obj) {
        BEAN_MAP.put(cls, obj);
    }

    /**
     * 获取基础包名下所有 Service 类
     */
    public static Set<Class<?>> getServiceClassSet() {
        return ClassHelper.getClassSetByAnnotation(Service.class);
    }

    /**
     * 获取基础包名下所有 Controller 类
     */
    public static Set<Class<?>> getControllerClassSet() {
        return ClassHelper.getClassSetByAnnotation(Controller.class);
    }

    /**
     * 获取基础包名下所有 Bean 类（包括：Controller、Service）
     */
    public static Set<Class<?>> getBeanClassSet() {
        Set<Class<?>> beanClassSet = new HashSet<Class<?>>();
        beanClassSet.addAll(getServiceClassSet());
        beanClassSet.addAll(getControllerClassSet());
        return beanClassSet;
    }
}
